package com.huarui.sale.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.ewaf.framework.model.ListModel;
import org.ewaf.framework.service.BaseService;
import org.ewaf.framework.util.BeanUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import com.huarui.code.dao.ICodeGenericDao;
import com.huarui.code.model.CodeGeneric;
import com.huarui.dictionary.DictionaryEnum;
import com.huarui.inventory.dao.IInventoryDao;
import com.huarui.inventory.model.Inventory;
import com.huarui.part.dao.IPartDao;
import com.huarui.partner.dao.IPartnerDao;
import com.huarui.partner.model.Partner;
import com.huarui.payable.dao.IPayableDao;
import com.huarui.payable.model.Payable;
import com.huarui.purchaseOrder.model.PurOrSaleOrder;
import com.huarui.quotation.service.QuotationService;
import com.huarui.receivable.dao.IReceivableDao;
import com.huarui.receivable.model.Receivable;
import com.huarui.sale.button.SaleButtonService;
import com.huarui.sale.dao.IExpressDao;
import com.huarui.sale.dao.IExpressItemDao;
import com.huarui.sale.dao.ISaleDao;
import com.huarui.sale.dao.ISaleItemDao;
import com.huarui.sale.model.Express;
import com.huarui.sale.model.ExpressItem;
import com.huarui.sale.model.Sale;
import com.huarui.sale.model.SaleItem;
import com.huarui.sale.util.SaleConstantEnum;
import com.huarui.saleOrder.dao.ISaleOrderDao;
import com.huarui.saleOrder.dao.ISaleOrderDetailsDao;
import com.huarui.saleReturn.util.ConstantParamEnum;
import com.huarui.user.dao.IUserDao;
import com.huarui.user.model.SessionMessage;
import com.huarui.user.model.User;
import com.huarui.user.security.UserHolder;

public class SaleService extends BaseService {

	private ISaleItemDao saleItemDao;

	private IExpressDao expressDao;

	private IExpressItemDao expressItemDao;

	private IInventoryDao inventoryDao;

	private ICodeGenericDao codeGenericDao;

	private SaleButtonService saleButtonService;

	private IPartDao partDao;

	private IPartnerDao partnerDao;
	
	private IReceivableDao receivableDao;
	
	private IPayableDao payableDao;	
	
	private IUserDao userDao;
	
	private ISaleOrderDao saleOrderDao;
	
	private ISaleOrderDetailsDao saleOrderDetailsDao;
	
	private QuotationService quotationService;
	
	private ISaleDao getDao() {

		return (ISaleDao) dao;
	}

	/**
	 * 根据单据号和公司id查询销售单
	 * 
	 * @param code
	 *            单据号
	 * @param companyId
	 *            公司id
	 * @return
	 */
	public Sale getSaleByCodeAndCompanyId(String code, int companyId) {

		return getDao().getSaleByCodeAndCompanyId(code, companyId);
	}

	@SuppressWarnings("unchecked")
	public ListModel<Sale> getSaleListForPage(Map<String, Object> queryMap,ListModel lm) {
		Integer total = getDao().getSaleCount(queryMap);
		lm.setTotal(total);
		queryMap.put("listModel", lm);
		List<Sale> reList = getDao().getSalePage(queryMap);
		lm.setResult(reList);
		return lm;
	}

	@SuppressWarnings("unchecked")
	public ListModel<Map<String, Object>> getSaleIdPage(Map<String, Object> queryMap, ListModel lm) {
		Integer total = getDao().getSaleCount(queryMap);
		lm.setTotal(total);
		queryMap.put("listModel", lm);
		List<Map<String, Object>> list = getDao().getSaleIdPage(queryMap);
		lm.setResult(list);
		return lm;
	}

	
	public JSONObject backupCreate(String queryParam) {
		final JSONObject saleInfo = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();		
		JSONObject result = (JSONObject) transactionTemplate.execute(new TransactionCallback() {
					@SuppressWarnings("unchecked")
					@Override
					public Object doInTransaction(TransactionStatus status) {
						Map saleMap = generateSaleInfo(saleInfo);
						Sale sale = (Sale) saleMap.get(SaleConstantEnum.SALE.getType());
						JSONObject response = new JSONObject();
					    response = handleSaleAndItemsWithExpress(saleMap, sale, Sale.STATUS_CREATE, SaleConstantEnum.CREATEORNAME.getType(), SaleConstantEnum.SAVE_CREATE_SUCCESS.getType(), sessionMessage, false);
						if(response != null){
							return response;
						}
						//更新orderItem的pickedQuantity
						List<Map> orderMap = (List<Map>) saleMap.get(SaleConstantEnum.ORDERPICKEDRECORD.getType());
						if (orderMap !=null && !orderMap.isEmpty()) {
							saleOrderDetailsDao.batchUpdateSaleOrderPickedQty(orderMap);
						}
						response =generateResponse(sale,sessionMessage);
						return response;
					}
				});
		return result;
	}

	private void batchDeleteExpress(List<Integer> expressDeleteIds,Integer companyId) {
		Map<String,Object> map = new HashMap<String, Object>();
		map.put(SaleConstantEnum.IDS.getType(), expressDeleteIds);
		map.put(SaleConstantEnum.BUYERID.getType(), companyId);
		expressDao.batchDeleteExpress(map);
	}

	public JSONObject backupSubmit(String queryParam) {
		final JSONObject saleInfo = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();		
		JSONObject result = (JSONObject) transactionTemplate.execute(new TransactionCallback() {
					@SuppressWarnings("unchecked")
					@Override
					public Object doInTransaction(TransactionStatus status) {
						Map saleMap = generateSaleInfo(saleInfo);
						Sale sale = (Sale) saleMap.get(SaleConstantEnum.SALE.getType());
						sale.setSubmitter(sessionMessage.getUserId());
						JSONObject response = new JSONObject();
					    response = handleSaleAndItemsWithExpress(saleMap, sale, Sale.STATUS_SUBMIT, SaleConstantEnum.SUBMITTERNAME.getType(), SaleConstantEnum.SAVE_SUBMIT_SUCCESS.getType(), sessionMessage, false);
						if(response != null){
							return response;
						}
						//更新orderItem的pickedQuantity
						List<Map> orderMap = (List<Map>) saleMap.get(SaleConstantEnum.ORDERPICKEDRECORD.getType());
						if (orderMap !=null && !orderMap.isEmpty()) {
							saleOrderDetailsDao.batchUpdateSaleOrderPickedQty(orderMap);
						}
						response =generateResponse(sale,sessionMessage);
						return response;
					}
				});
		return result;
	}
	
	public JSONObject backupDelivery(String queryParam) {
		final JSONObject saleInfo = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();		
		JSONObject result = (JSONObject) transactionTemplate.execute(new TransactionCallback() {
					@SuppressWarnings("unchecked")
					@Override
					public Object doInTransaction(TransactionStatus status) {
						Map saleMap = generateSaleInfo(saleInfo);
						Sale sale = (Sale) saleMap.get(SaleConstantEnum.SALE.getType());
						JSONObject response = new JSONObject();
					    response = handleSaleAndItemsWithExpress(saleMap, sale, Sale.STATUS_DELIVERY, SaleConstantEnum.DELIVERYNAME.getType(), SaleConstantEnum.SAVE_DELIVERY_SUCCESS.getType(), sessionMessage, true);
						if(response != null){
							return response;
						}						
						// saleItem新增明细
						List<SaleItem> addedSaleItems = (List<SaleItem>) saleMap.get(SaleConstantEnum.ADDEDSALEITEMS.getType());
						// saleItem修改明细
						List<SaleItem> modifiedSaleItems = (List<SaleItem>) saleMap.get(SaleConstantEnum.MODIFIEDSALEITEMS.getType());
						// express
						List<Express> expresses = (List<Express>) saleMap.get(SaleConstantEnum.EXPRESS.getType());	
						// 修改expressItem
						List<ExpressItem> modifiedExpressItems = (List<ExpressItem>) saleMap.get(SaleConstantEnum.MODIFIEDEXPRESSITEMS.getType());
						// 新增expressItem
						List<ExpressItem> addedExpressItems = (List<ExpressItem>) saleMap.get(SaleConstantEnum.ADDEDEXPRESSITEMS.getType());
						
						Map<String,Object> modifiedItems = generateModifiedInventories(addedSaleItems, modifiedSaleItems, sessionMessage);
												
						List<Inventory> modifiedInventories = (List<Inventory>) modifiedItems.get(SaleConstantEnum.MODIFIEDINVENTORY.getType());
						if (!modifiedInventories.isEmpty()) {
							//修改库存表,库存件设置库存剩余数,急件明细在库存表中生成新纪录						
							inventoryDao.batchUpdateInventory(modifiedInventories);
							//更新零件属性表,报价表
							quotationService.handlePartPropertyAndQuotation(modifiedInventories,false);
						}
						Map<String,Object> addedItems = generateAddedItems(expresses, sessionMessage);
						
						List<Inventory> addedInventories = (List<Inventory>) addedItems.get(SaleConstantEnum.ADDEDINVENTORY.getType());
						if (!addedInventories.isEmpty()) {
							inventoryDao.batchInsertInventory(addedInventories);
							//急件明细插入inventory后保存零件属性表,报价表
							quotationService.handlePartPropertyAndQuotation(addedInventories,true);
						}
						handlelPartner(sale, addedItems);						
						
						//更新expressItem的inventoryIdBySeller
						List<ExpressItem> exItemsWithoutInventoryId = new ArrayList<ExpressItem>();
						exItemsWithoutInventoryId.addAll(modifiedExpressItems);
						exItemsWithoutInventoryId.addAll(addedExpressItems);
						expressItemDao.batchUpdateExpressItemInventoryId(exItemsWithoutInventoryId);																																														
						//生成应收款记录(销售)
						Receivable receivable = handleReceiveable(sessionMessage, sale);
						//生成应付款记录(急件)
						handlePayable(sessionMessage, expresses);
						//更改销售订单状态
						if(sale.getOrdersId() != null){
							Map<String,Object> map = new HashMap<String,Object>();
							map.put("status", PurOrSaleOrder.STATUS_SELLER_DELIVERY);
							map.put("id", sale.getOrdersId());
							map.put("sellerId", sessionMessage.getCompanyId());
							map.put("saleId", sale.getId());
							saleOrderDao.updateSaleOrderStatus(map);							
						}												
						response =generateResponse(sale,sessionMessage);
						response.put(SaleConstantEnum.RECEIVABLEID.getType(), receivable.getId());
						response.put(SaleConstantEnum.CUSTOMERID.getType(), receivable.getCustomerId());
						return response;
					}
				});
		return result;
	}	


	@SuppressWarnings("unchecked")
	private JSONObject handleSaleAndItemsWithExpress(Map saleMap,Sale sale,String status,String keyName,String lastMsg,SessionMessage sessionMessage,boolean isDelivery){
		// saleItem新增明细
		List<SaleItem> addedSaleItems = (List<SaleItem>) saleMap.get(SaleConstantEnum.ADDEDSALEITEMS.getType());
		// saleItem修改明细
		List<SaleItem> modifiedSaleItems = (List<SaleItem>) saleMap.get(SaleConstantEnum.MODIFIEDSALEITEMS.getType());
		// express
		List<Express> expresses = (List<Express>) saleMap.get(SaleConstantEnum.EXPRESS.getType());
		// saleItem删除明细ids
		List<Map> saleItemDeletedIds = (List<Map>) saleMap.get(SaleConstantEnum.SALEITEMDELETEDIDS.getType());
		// expressItem删除明细ids
		List<Map> expressItemDeletedIds = (List<Map>) saleMap.get(SaleConstantEnum.EXPRESSITEMDELETEDIDS.getType());
		//express删除id
		List<Integer> expressDeleteIds = (List<Integer>) saleMap.get(SaleConstantEnum.EXPRESSDELETEIDS.getType());
		JSONObject response = new JSONObject();
		if (sale.getId() == null) {
			if(sale.getOrdersId() != null){
				//首次保存销售草稿单据,判断此引用订单是否已被其他人处理完毕
				Integer saleId = getDao().getSaleIdByOrdersId(sale.getOrdersId());
				if(saleId != null){
					Map saMap = getSaleForMapById(saleId);
					response.put(SaleConstantEnum.SUCCESS.getType(), false);
					response.put(SaleConstantEnum.MSG.getType(), "该销售订单已由"+(String)saMap.get(keyName)+lastMsg);
					return response;
				}else{
					//清空orders的currentorId									
					saleOrderDao.clearSaleOrderCurrentorById(sale.getOrdersId());
				}								
			}	
			// 首次保存销售单待出货单据
			String codeOfSeller = codeGenericDao.getNewCode(sessionMessage.getCompanyId(),CodeGeneric.SALE);
			sale.setCodeOfSeller(codeOfSeller);
			sale.setCreatorId(sessionMessage.getUserId());
			sale.setSellerId(sessionMessage.getCompanyId());
			sale.setCurrentorId(sessionMessage.getUserId());
			sale.setStatus(status);
			if(isDelivery){
				sale.setDeliveryerId(sessionMessage.getUserId());
				if(sale.getSubmitter() == null){
					sale.setSubmitter(sessionMessage.getUserId());
				}
				sale.setCurrentorId(null);
			}			
			getDao().create(sale);
		} else {
			response = checkCurrentorIdBeforeUpdate(sessionMessage, sale);
			if(response != null){
				return response;
			}
			sale.setStatus(status);
			if(isDelivery){
				sale.setDeliveryerId(sessionMessage.getUserId());
				if(sale.getSubmitter() == null){
					sale.setSubmitter(sessionMessage.getUserId());
				}
				sale.setCurrentorId(null);
			}
			getDao().update(sale);
		}
		if (addedSaleItems != null && addedSaleItems.size() > 0) {
			addedSaleItems = setSaleItemSaleId(sale,addedSaleItems);
			saleItemDao.batchInsertSaleItem(addedSaleItems);
		}
		if (modifiedSaleItems != null&& modifiedSaleItems.size() > 0) {
			saleItemDao.batchUpdateSaleItem(modifiedSaleItems);
		}
		if (saleItemDeletedIds != null&& saleItemDeletedIds.size() > 0) {
			saleItemDao.batchDeleteSaleItemByIds(saleItemDeletedIds);
		}				
		// 新增expressItem
		List<ExpressItem> addedExpressItems = new ArrayList<ExpressItem>();
		// 修改expressItem
		List<ExpressItem> modifiedExpressItems = new ArrayList<ExpressItem>();
		
		if (expresses != null && expresses.size() > 0) {
			for (Express express : expresses) {
				express.setSaleId(sale.getId());
				express.setBuyerId(sessionMessage.getCompanyId());
				BeanUtils.copyProperties(sale, express,new String[] { "id", "sellerId","codeOfSeller", "amount","buyerId" });
				if (express.getId() == null) {
					String codeOfBuyer = codeGenericDao.getNewCode(sessionMessage.getCompanyId(),CodeGeneric.EXPRESS);
					express.setCodeOfBuyer(codeOfBuyer);
					expressDao.create(express);
					List<ExpressItem> expressItems = express.getExpressItems();
					expressItems = setExpressItemExpressId(express, expressItems);
					addedExpressItems.addAll(expressItems);
				} else {
					expressDao.update(express);
					List<ExpressItem> expressItems = express.getExpressItems();
					for (ExpressItem expressItem : expressItems) {
						if (expressItem.getId() == null) {
							expressItem.setExpressId(express.getId());
							addedExpressItems.add(expressItem);
						} else {
							modifiedExpressItems.add(expressItem);
						}
					}
				}
			}
		}
		saleMap.put(SaleConstantEnum.ADDEDEXPRESSITEMS.getType(), addedExpressItems);
		saleMap.put(SaleConstantEnum.MODIFIEDEXPRESSITEMS.getType(), modifiedExpressItems);
		
		if(expressDeleteIds != null && expressDeleteIds.size() > 0){
			batchDeleteExpress(expressDeleteIds,sessionMessage.getCompanyId());
		}
		if (addedExpressItems != null&& addedExpressItems.size() > 0) {
			expressItemDao.batchInsertExpressItem(addedExpressItems);
		}
		if (modifiedExpressItems != null&& modifiedExpressItems.size() > 0) {
			expressItemDao.batchUpdateExpressItem(modifiedExpressItems);
		}
		if (expressItemDeletedIds != null&& expressItemDeletedIds.size() > 0) {
			expressItemDao.bacthDeleteExpressItemByIds(expressItemDeletedIds);
		}
		
		return null;
	}
	
	@SuppressWarnings("unchecked")
	private void handlelPartner(Sale sale,
			Map<String, Object> addedItems) {
		List<Partner> partners = (List<Partner>) addedItems.get(SaleConstantEnum.PARTNER.getType());											
		Partner partner = partnerDao.getByIdForUpdate(sale.getPartnerIdBySeller());
		BigDecimal unReceived = partner.getUnreceived();
		if(unReceived == null ){
			unReceived = new BigDecimal(0);
		}
		unReceived = unReceived.add(sale.getAmount());
		partner.setUnreceived(unReceived);						
		partners.add(partner);	
		//更新销售单买方应收款，急件卖方应付款
		partnerDao.batchUpdatePartner(partners);
	}

	private void handlePayable(final SessionMessage sessionMessage,List<Express> expresses) {
		List<Payable> payables = new ArrayList<Payable>();
		if(expresses != null && expresses.size() > 0){
			for(Express express : expresses){
				String payableCode = codeGenericDao.getNewCode(sessionMessage.getCompanyId(),CodeGeneric.PAYABLE); // 应付款凭证号				
				Payable payable = new Payable();			
				payable.setCode(payableCode);
				payable.setCompanyId(sessionMessage.getCompanyId());
				payable.setCustomerId(express.getPartnerIdByBuyer());
				payable.setDocumentType(Inventory.DDOCUMENT_TYPE_EXPRESS);
				payable.setDocumentId(express.getId());
				payable.setDocumentCode(express.getCodeOfBuyer());
				payable.setPayable(express.getAmount());
				payable.setPaid(new BigDecimal(0));
				payable.setStatus(Payable.STATUS_UNCOMPLETE);
				payables.add(payable);
			}
		}
		payableDao.batchInsertPayable(payables);
	}					
	
	/**
	 * 库存件出库修改inventory
	 * @param addedSaleItems
	 * @param modifiedSaleItems
	 * @param sessionMessage
	 * @return
	 */
	private Map<String,Object> generateModifiedInventories(List<SaleItem> addedSaleItems,List<SaleItem> modifiedSaleItems,SessionMessage sessionMessage) {	
		List<Inventory> modifiedInventories = new ArrayList<Inventory>();		
		List<SaleItem> saleItems = new ArrayList<SaleItem>();
		if(addedSaleItems != null && addedSaleItems.size() >0){
			saleItems.addAll(addedSaleItems);
		}
		if(modifiedSaleItems != null && modifiedSaleItems.size() > 0){
			saleItems.addAll(modifiedSaleItems);
		}
		for(SaleItem saleItem : saleItems){
			//库存
			Inventory inventory = inventoryDao.getInventoryByIdAndCompanyId(saleItem.getInventoryIdBySeller(),sessionMessage.getCompanyId(),true);
			Integer inventoryOnHand = inventory.getOnHand()-saleItem.getQuantity();
			if(inventoryOnHand < 0){
				inventoryOnHand = 0;
			}
			inventory.setOnHand(inventoryOnHand);
			inventory.setChangeQuantity(saleItem.getQuantity());
			inventory.setGmtLastType(Inventory.GMTLASTTYPE_SOLD);
			modifiedInventories.add(inventory);
		}	
		Map<String,Object> map = new HashMap<String, Object>();
		map.put(SaleConstantEnum.MODIFIEDINVENTORY.getType(), modifiedInventories);
		return map;
	}
	
	
	
	private Map<String,Object> generateAddedItems(List<Express> expresses,SessionMessage sessionMessage) {
		List<Inventory> adddedInventories = new ArrayList<Inventory>();
		List<Partner> partners = new ArrayList<Partner>();
		if(expresses != null && expresses.size() > 0){
			for(Express express : expresses){
				List<ExpressItem> expressItems = express.getExpressItems();
				for(ExpressItem expressItem : expressItems){
					Partner partner = partnerDao.getByIdForUpdate(express.getPartnerIdByBuyer());
				    //库存
					Inventory inventory = new Inventory();
					BeanUtils.copyProperties(expressItem, inventory, new String[]{"id"});
					inventory.setCompanyId(sessionMessage.getCompanyId());
					inventory.setInitQuantity(expressItem.getBuyQuantity());
					inventory.setOnHand(expressItem.getBuyQuantity()-expressItem.getSaleQuantity());
					inventory.setDocumentType(Inventory.DDOCUMENT_TYPE_EXPRESS);
					inventory.setDocumentId(express.getId());
					inventory.setDocumentCode(express.getCodeOfBuyer());					
					inventory.setPartnerId(partner.getId());
					inventory.setPartnerName(partner.getName());
					inventory.setChangeQuantity(expressItem.getBuyQuantity()-expressItem.getSaleQuantity());
					adddedInventories.add(inventory);
					
					//急件供货商,更新未付款				
					BigDecimal unPaid = partner.getUnpaid();
					if(unPaid == null){
						unPaid = new BigDecimal(0);
					}
					partner.setUnpaid(unPaid.add(express.getAmount()));
					partners.add(partner);
				}
 			}
		}
		Map<String,Object> map = new HashMap<String,Object>();
		map.put(SaleConstantEnum.ADDEDINVENTORY.getType(), adddedInventories);
		map.put(SaleConstantEnum.PARTNER.getType(), partners);
		return map;
	}
    /**
     * 返回sale,saleItem,express,expressItem,buttons
     * @param sale
     * @param sessionMessage
     * @return
     */
	@SuppressWarnings("unchecked")
	private JSONObject generateResponse(Sale sale,SessionMessage sessionMessage) {
		//sale主表
		Map<String,Object> queryMap = new HashMap<String, Object>();
		queryMap.put(SaleConstantEnum.ID.getType(), sale.getId());
		queryMap.put(SaleConstantEnum.VARGROUP.getType(), DictionaryEnum.GROUP_SALE_STATUS.getGroup());
		queryMap.put(SaleConstantEnum.COMPANYID.getType(), sessionMessage.getCompanyId());
		Map<String,Object> saleMap = getDao().getSaleForMapByConditions(queryMap).get(0);
		//saleItem
		queryMap.clear();
		queryMap.put(SaleConstantEnum.SALEID.getType(), sale.getId());
		queryMap.put(SaleConstantEnum.VARGROUP.getType(), DictionaryEnum.GROUP_SOURCE.getGroup());
		List<Map<String,Object>> saleItemMaps = saleItemDao.getSaleItemForMap(queryMap);
		//express主表
		List<Map<String,Object>> expressMaps = expressDao.getExpressForMapBySaleId(sale.getId());
		List<JSONObject> expressAndItems = new ArrayList<JSONObject>();
		for(Map expressMap : expressMaps){
			JSONObject expressAndItem = new JSONObject();
			//expressItem明细
			List<Map<String,Object>> expressItemMap = expressItemDao.getExpressItemForMapByExpressId((Integer)expressMap.get(SaleConstantEnum.ID.getType()));
			expressAndItem.accumulate(SaleConstantEnum.EXPRESS.getType(), expressMap);
			expressAndItem.accumulate(SaleConstantEnum.EXPRESSITEM.getType(),expressItemMap);
			expressAndItems.add(expressAndItem);			
		}
		//状态按钮
		JSONObject buttons = saleButtonService.getButttonsBySatatus(sale.getStatus(), sale.getCurrentorId(), sessionMessage.getUserId());
		JSONObject response = new JSONObject();
		response.put(SaleConstantEnum.SALE.getType(), saleMap);
		response.put(SaleConstantEnum.SALEITEM.getType(), saleItemMaps);
		response.put(SaleConstantEnum.EXPRESS.getType(), expressAndItems);
		response.put(SaleConstantEnum.BUTTONS.getType(), buttons);
		return response;
	}

	/**
	 * 设置saleItem的saleId
	 * 
	 * @param sale
	 * @param addedSaleItem
	 * @return
	 */
	private List<SaleItem> setSaleItemSaleId(Sale sale,List<SaleItem> addedSaleItem) {
		List<SaleItem> newsSaleItems = new ArrayList<SaleItem>();
		for (SaleItem saleItem : addedSaleItem) {
			saleItem.setSaleId(sale.getId());
			newsSaleItems.add(saleItem);
		}
		return newsSaleItems;
	}

	// 设置expressItem的expressId
	private List<ExpressItem> setExpressItemExpressId(Express express,List<ExpressItem> expressItems) {
		List<ExpressItem> newExpressItems = new ArrayList<ExpressItem>();
		for (ExpressItem expressItem : expressItems) {
			expressItem.setExpressId(express.getId());
			newExpressItems.add(expressItem);
		}
		return newExpressItems;
	}

	@SuppressWarnings("unchecked")
	private Map generateSaleInfo(JSONObject saleInfo) {
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		JSONObject saleObject = saleInfo.getJSONObject(SaleConstantEnum.SALE.getType());
		// sale主表
		Sale sale = (Sale) JSONObject.toBean(saleObject, Sale.class);
		//Sale sale = JsonUtil.getBean(saleObject, Sale.class, "yyyy-MM-dd");
		if (sale.getId() == null) {
			sale.setSellerId(sessionMessage.getCompanyId());
		} else {
			Sale sale2 = getSaleById(sale.getId(), sessionMessage.getCompanyId(), false);
			BeanUtils.copyProperties(sale2, sale, new String[] { "buyerId","partnerIdBySeller", "memoOfSeller", "areaId", "province","city", "district", "street", "postCode", "receiverName","phone", "mobile", "transportType" });
		}
		JSONArray saleItemArray = saleInfo.getJSONArray(SaleConstantEnum.SALEITEM.getType());
		// saleItem明细
		List<SaleItem> saleItems = (List<SaleItem>) JSONArray.toCollection(saleItemArray, SaleItem.class);
		// saleItem修改明细
		List<SaleItem> modifySaleItems = new ArrayList<SaleItem>();
		// saleItem新增明细
		List<SaleItem> addSaleItems = new ArrayList<SaleItem>();
		//修改pickedQuantity的order
		JSONArray orderPickQtyArr = saleInfo.getJSONArray(SaleConstantEnum.ORDERPICKEDRECORD.getType());
		List<Map> orderPickQtys = (List<Map>) JSONArray.toCollection(orderPickQtyArr, Map.class);
		// 金额
		BigDecimal totalAmount = new BigDecimal(0);
		if (saleItems != null && saleItems.size() > 0) {
			for (SaleItem saleItem : saleItems) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put(SaleConstantEnum.CODE.getType(), saleItem.getCode());
				map.put(SaleConstantEnum.SOURCE.getType(), saleItem.getSource());
				Map part = partDao.getPartByConditionsJson(map);
				BeanUtil.copyProperties(saleItem,part);
				BigDecimal retailAmount = saleItem.getPrice().multiply(new BigDecimal(saleItem.getQuantity()));
				saleItem.setRetailAmount(retailAmount);
				totalAmount = totalAmount.add(retailAmount);
				if (saleItem.getId() == null) {
					addSaleItems.add(saleItem);
				} else {
					modifySaleItems.add(saleItem);
				}
			}
		}
		JSONArray expressAndItemArray = saleInfo.getJSONArray(SaleConstantEnum.EXPRESS.getType());
		List<Express> expresses = new ArrayList<Express>();
		if (expressAndItemArray.size() > 0 ) {
			for (int i = 0; i < expressAndItemArray.size(); i++) {
				JSONObject expressAndItemObject = expressAndItemArray.getJSONObject(i);
				JSONObject expressObject = (JSONObject) expressAndItemObject.getJSONObject(SaleConstantEnum.EXPRESS.getType());
				JSONArray expressItemArray = (JSONArray) expressAndItemObject.getJSONArray(SaleConstantEnum.EXPRESSITEM.getType());
				// express主表
				Express express = (Express) JSONObject.toBean(expressObject,Express.class);
				// expressItem明细表
				List<ExpressItem> expressItems = (List<ExpressItem>) JSONArray.toCollection(expressItemArray, ExpressItem.class);
				List<ExpressItem> expressItemsAfterHandle = new ArrayList<ExpressItem>();
				BigDecimal expressAmount = new BigDecimal(0);
				if (expressItems != null && expressItems.size() > 0) {
					for (ExpressItem expressItem : expressItems) {
						Map<String, Object> queryMap = new HashMap<String, Object>();
						queryMap.put(SaleConstantEnum.CODE.getType(),expressItem.getCode());
						queryMap.put(SaleConstantEnum.SOURCE.getType(),expressItem.getSource());
						Map part = partDao.getPartByConditionsJson(queryMap);						
						BeanUtil.copyProperties(expressItem, part);
						BigDecimal retailAmount = expressItem.getRetailPrice().multiply(new BigDecimal(expressItem.getSaleQuantity()));
						BigDecimal costAmount = expressItem.getCost().multiply(new BigDecimal(expressItem.getBuyQuantity()));
						expressItem.setCostAmount(costAmount);
						expressItem.setRetailAmount(retailAmount);
						expressAmount = expressAmount.add(retailAmount);
						expressItemsAfterHandle.add(expressItem);
					}
				}
				express.setAmount(expressAmount);
				BeanUtils.copyProperties(sale, express, new String[] { "id","sellerId", "codeOfSeller", "amount", "buyerId" });
				totalAmount = totalAmount.add(expressAmount);
				express.setExpressItems(expressItemsAfterHandle);
				expresses.add(express);
			}
		}
		sale.setAmount(totalAmount);
		// saleItem删除明细ids
		JSONArray saleItemDeleteIdArr = saleInfo.getJSONArray(SaleConstantEnum.SALEITEMDELETEDIDS.getType());
		List<Map> saleItemDeleteIds = (List<Map>) JSONArray.toCollection(saleItemDeleteIdArr, Map.class);
		// expressItem删除明细ids
		JSONArray expressItemDeleteIdArr = saleInfo.getJSONArray(SaleConstantEnum.EXPRESSITEMDELETEDIDS.getType());
		List<Map> expressItemDeleteIds = (List<Map>) JSONArray.toCollection(expressItemDeleteIdArr, Map.class);
		//express删除Id
		JSONArray expressDeleteIdArr = saleInfo.getJSONArray(SaleConstantEnum.EXPRESSDELETEIDS.getType());
		List<Integer> expressDeleteIds = (List<Integer>) JSONArray.toCollection(expressDeleteIdArr, Integer.class);
		Map dataMap = new HashMap();
		dataMap.put(SaleConstantEnum.SALE.getType(), sale);
		dataMap.put(SaleConstantEnum.ADDEDSALEITEMS.getType(), addSaleItems);
		dataMap.put(SaleConstantEnum.MODIFIEDSALEITEMS.getType(),modifySaleItems);
		dataMap.put(SaleConstantEnum.EXPRESS.getType(), expresses);
		dataMap.put(SaleConstantEnum.SALEITEMDELETEDIDS.getType(),saleItemDeleteIds);
		dataMap.put(SaleConstantEnum.EXPRESSITEMDELETEDIDS.getType(),expressItemDeleteIds);
		dataMap.put(SaleConstantEnum.EXPRESSDELETEIDS.getType(), expressDeleteIds);
		dataMap.put(SaleConstantEnum.ORDERPICKEDRECORD.getType(), orderPickQtys);
		return dataMap;
	}

	private Sale getSaleById(Integer id, Integer companyId, boolean update) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(SaleConstantEnum.ID.getType(), id);
		map.put(SaleConstantEnum.SELLERID.getType(), companyId);
		map.put(SaleConstantEnum.UPDATE.getType(), update);
		Sale sale = getDao().getSaleById(map);
		return sale;
	}
	
	 /**
     * 根据id查询主表，明细，及获得按钮
     * @param saleReturnId
     * @return
     */
	@SuppressWarnings("unchecked")
	public JSONObject getSaleAndItemsById(Integer saleId) {
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		Sale sale = getSaleById(saleId, sessionMessage.getCompanyId(), false);
		JSONObject response = generateResponse(sale, sessionMessage);
		Map salMap = (Map) response.get(SaleConstantEnum.SALE.getType());
		String status = (String) salMap.get(SaleConstantEnum.STATUS.getType());
		Integer orderId = (Integer) salMap.get(SaleConstantEnum.ORDERSID.getType());
		if(orderId != null && status.equals(Sale.STATUS_CREATE)){
			response.put("withOrder", true);				
			// 封装销售订单明细表信息		
			List<Map<String, Object>> detailMap = saleOrderDetailsDao.getSaleOrderDetailByOrderId(orderId);
			response.put("orderItem", detailMap);
		}
		return response;
	}
	/**
	 * 设置sale的currentorId
	 * @param saleId
	 * @param userId
	 * @return
	 */
	public JSONObject updateSaleCurrentorId(Integer saleId, Integer userId) {
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		Map<String,Object> map = new HashMap<String,Object>();
		map.put(SaleConstantEnum.ID.getType(), saleId);
		map.put(SaleConstantEnum.CURRENTORID.getType(), userId);
		map.put(SaleConstantEnum.SELLERID.getType(), sessionMessage.getCompanyId());
		getDao().updateSaleCurrentorId(map);
		Sale sale = getSaleById(saleId, sessionMessage.getCompanyId(), false);
		JSONObject buttons = saleButtonService.getButttonsBySatatus(sale.getStatus(),sale.getCurrentorId(),sessionMessage.getUserId());
		return buttons;
	}
	/**
	 * 删除草稿
	 * @param id
	 * @return
	 */
	public JSONObject deleteSaleById(Integer id){
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		Sale sale = getSaleById(id, sessionMessage.getCompanyId(), false);	
		JSONObject response = checkCurrentorIdBeforeUpdate(sessionMessage,sale);
		if(response != null){
			return response;
		}
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put(SaleConstantEnum.ID.getType(), id);
		map.put(SaleConstantEnum.SELLERID.getType(), sessionMessage.getCompanyId());
		boolean success = getDao().deleteById(map);
		expressDao.deleteExpressBySaleId(id);
		JSONObject resp = new JSONObject();
		if(success){
			resp.put(SaleConstantEnum.SUCCESS.getType(), true);
			resp.put(SaleConstantEnum.MSG.getType(), SaleConstantEnum.DELETE_DRAFT_SUCCESS.getType());
		}else{
			resp.put(SaleConstantEnum.SUCCESS.getType(), false);
			resp.put(SaleConstantEnum.MSG.getType(), SaleConstantEnum.DRAFT_NOT_EXIST.getType());
		}
		return resp;
	}
	/**
	 * 待仓库审核状态退回草稿状态
	 * @return
	 */
	public JSONObject updateSaleStatusById(final Integer id) {
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		JSONObject result = (JSONObject) transactionTemplate.execute(new TransactionCallback() {			
			@Override
			public Object doInTransaction(TransactionStatus status) {
				Sale sale = getSaleById(id, sessionMessage.getCompanyId(), true);
				JSONObject response = checkCurrentorIdBeforeUpdate(sessionMessage,sale);
				if(response != null){
					return response;
				}
				sale.setStatus(Sale.STATUS_CREATE);
				sale.setSubmitter(null);
				getDao().update(sale);
				List<Express> expresses = expressDao.getExpressBySaleId(id);
				if(expresses != null && expresses.size() > 0){
					for(Express express : expresses){
						BeanUtils.copyProperties(sale, express,new String[] { "id", "sellerId","codeOfSeller", "amount","buyerId" });
					}
				}
				expressDao.batchUpdateExpress(expresses);
				JSONObject resp = generateResponse(sale, sessionMessage);
				return resp;
			}
		});
		return result;
	}
	
	private JSONObject checkCurrentorIdBeforeUpdate(SessionMessage sessionMessage, Sale sale) {
		Integer currentorId = sale.getCurrentorId();
		Integer userId =sessionMessage.getUserId();
		String msg;	
		JSONObject response = new JSONObject();
		if(sale.getDeliveryerId() != null && sale.getStatus().equals(Sale.STATUS_DELIVERY)){
			String deliveryName = ((User)userDao.getById(sale.getDeliveryerId())).getName();
			msg = SaleConstantEnum.MSG_AHEAD.getType()+deliveryName+SaleConstantEnum.MSG_HAS_COMPLETE.getType();
			response.put(SaleConstantEnum.MSG.getType(), msg);
			response.put(SaleConstantEnum.SUCCESS.getType(), false);
			return response;
		}
		if(currentorId != null && !currentorId.equals(userId)){
			String currentorName = ((User)userDao.getById(currentorId)).getName();
			msg = SaleConstantEnum.MSG_AHEAD.getType()+currentorName+SaleConstantEnum.MSG_ISNOT_OWNER.getType();
			response.put(SaleConstantEnum.MSG.getType(), msg);
			response.put(SaleConstantEnum.SUCCESS.getType(), false);
			return response;
		}
		return null;
	}
	
	/**
	 * 查询销售单
	 * @param queryMap
	 * @param saleListModel
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ListModel getSaleListModelByConditions(Map queryMap,ListModel saleListModel) {
		queryMap.put(SaleConstantEnum.VARGROUP.getType(),DictionaryEnum.GROUP_SALE_STATUS.getGroup());
		queryMap.put(SaleConstantEnum.COMPANYID.getType(), UserHolder.getCurrentSessionMessage().getCompanyId());
		saleListModel.setTotal(getDao().getSaleCount(queryMap));
		if (saleListModel.getOrderBy() == null) {
			saleListModel.setOrderBy(ConstantParamEnum.ORDERBY_GMTREALDELIVERY.getType());
		}
		queryMap.put(ConstantParamEnum.LISTMODEL.getType(), saleListModel);
		List<Map> sales = getDao().getSaleForMapByConditions(queryMap);
		saleListModel.setResult(sales);
		return saleListModel;
	}
	/**
	 * 查询销售库存件明细
	 * @param queryMap
	 * @param saleListModel
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ListModel<Map> getSaleItemListMdelByConditions(Map queryMap,ListModel saleListModel) {
	     SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
	     queryMap.put(SaleConstantEnum.COMPANYID.getType(), sessionMessage.getCompanyId());
	     saleListModel.setTotal(saleItemDao.getSaleItemCountByConditions(queryMap));
	     if(saleListModel.getOrderBy() == null){
	    	 saleListModel.setOrderBy(SaleConstantEnum.CODEOFSELLER.getType());
	     }
	     queryMap.put(SaleConstantEnum.LISTMODEL.getType(), saleListModel);
	     List<Map> result = saleItemDao.getSaleItemForMapByConditions(queryMap);
	     saleListModel.setResult(result);	     
		 return saleListModel;
	}
	/**
	 * 查询销售单急件明细
	 * @param queryMap
	 * @param saleListModel
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ListModel<Map> getExpressItemListMdelByConditions(Map queryMap,ListModel expressItemListModel) {
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
	    queryMap.put(SaleConstantEnum.COMPANYID.getType(), sessionMessage.getCompanyId());
	    expressItemListModel.setTotal(expressItemDao.getExpressItemCountByConditions(queryMap));
	    if(expressItemListModel.getOrderBy() == null){
	    	 expressItemListModel.setOrderBy(SaleConstantEnum.CODEOFSELLER.getType());
	    }
	    queryMap.put(SaleConstantEnum.LISTMODEL.getType(), expressItemListModel);
	    List<Map> result = expressItemDao.getExpressItemForMapByConditions(queryMap);
	    expressItemListModel.setResult(result);
		return expressItemListModel;
	}

	@SuppressWarnings("unchecked")
	public JSONObject generateSaleAndItemsByOrderId(Integer orderId) {			
		Integer saleId = getDao().getSaleIdByOrdersId(orderId);
		JSONObject response = new JSONObject();		
		if(saleId != null){
			//该销售订单已被引用为销售出库单,销售单明细
			response = getSaleAndItemsById(saleId);
			Map salMap = (Map) response.get(SaleConstantEnum.SALE.getType());
			String status = (String) salMap.get(SaleConstantEnum.STATUS.getType());
			if(status.equals(Sale.STATUS_CREATE)){
				response.put("withOrder", true);				
				// 封装销售订单明细表信息		
				List<Map<String, Object>> detailMap = saleOrderDetailsDao.getSaleOrderDetailByOrderId(orderId);
				response.put("orderItem", detailMap);
			}
			response.put("hasSale", true);
		}else{
			//该销售订单未被引用为销售出库单
			response.put("hasSale", false);
			Map mainMap = saleOrderDao.getSaleOrderForMapById(orderId);
			String currentorName = (String) mainMap.get("currentorName");
			Integer currentorId = (Integer) mainMap.get("currentorId");
			Integer currentId = UserHolder.getCurrentSessionMessage().getUserId();			
			JSONObject msgObj = new JSONObject();
			if(currentorId == null || currentorId.equals(currentId)){
				msgObj.put("confirm", SaleConstantEnum.MSG_SURE_TO_CREATE.getType());
			}else{
				msgObj.put("confirm", currentorName + SaleConstantEnum.MSG_ALERT_TO_CREATE.getType());
			}
			response.put(SaleConstantEnum.MSG.getType(), msgObj);
		}			
		return response;
		
	}
	
	@SuppressWarnings("unchecked")
	private Map getSaleForMapById(Integer saleId) {
		Map<String,Integer> map = new HashMap<String,Integer>();
		map.put("id",saleId);
		List<Map> saleMap = getDao().getSaleForMapByConditions(map);
		return saleMap.size()>0?null:saleMap.get(0);
	}
	

	private Receivable handleReceiveable(final SessionMessage sessionMessage,Sale sale) {
		String code = codeGenericDao.getNewCode(sessionMessage.getCompanyId(),CodeGeneric.RECEIVABLE);
		Receivable receivable = new Receivable();
		receivable.setCompanyId(sessionMessage.getCompanyId());
		receivable.setCustomerId(sale.getPartnerIdBySeller());
		receivable.setCode(code);
		receivable.setDocumentType(Inventory.DDOCUMENT_TYPE_SALE);
		receivable.setDocumentId(sale.getId());
		receivable.setDocumentCode(sale.getCodeOfSeller());
		receivable.setReceivable(sale.getAmount());
		receivable.setReceived(new BigDecimal(0));
		receivable.setStatus(Receivable.STATUS_UNCOMPLETE);	
		receivableDao.create(receivable);
		return receivable;
	}

	public JSONObject acceptOrderToSaleByOrderId(Integer orderId) {
		SessionMessage sm = UserHolder.getCurrentSessionMessage();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("currentorId", sm.getUserId());
		map.put("currentorName", sm.getUserName());
		map.put("id", orderId);
		map.put("sellerId", sm.getCompanyId());	
		boolean success = saleOrderDao.updateSaleOrderCurrentor(map);
		JSONObject response = new JSONObject();	
		if(success){
			// 封装销售订单主表信息
			Map<String,Object> mainMap = saleOrderDao.getSaleOrderForMapById(orderId);		
			//JSONObject mainJson = JSONObject.fromObject(mainMap);
			// 封装销售订单明细表信息		
			List<Map<String, Object>> detailMap = saleOrderDetailsDao.getSaleOrderDetailByOrderId(orderId);
			//JSONArray detailJson = JSONArray.fromObject(detailMap);	
			response.put("order",mainMap );
			response.put("orderItem", detailMap);
			response.put(SaleConstantEnum.SUCCESS.getType(), true);				
		}else{
			response.put(SaleConstantEnum.SUCCESS.getType(), false);
			response.put(SaleConstantEnum.MSG.getType(),SaleConstantEnum.QUOTE_OREDERS_FAILURE.getType());				
		}					
		return response;
	}

	public void setSaleItemDao(ISaleItemDao saleItemDao) {
		this.saleItemDao = saleItemDao;
	}

	public void setExpressDao(IExpressDao expressDao) {
		this.expressDao = expressDao;
	}

	public void setExpressItemDao(IExpressItemDao expressItemDao) {
		this.expressItemDao = expressItemDao;
	}

	public void setInventoryDao(IInventoryDao inventoryDao) {
		this.inventoryDao = inventoryDao;
	}

	public void setCodeGenericDao(ICodeGenericDao codeGenericDao) {
		this.codeGenericDao = codeGenericDao;
	}

	public void setSaleButtonService(SaleButtonService saleButtonService) {
		this.saleButtonService = saleButtonService;
	}

	public void setPartDao(IPartDao partDao) {
		this.partDao = partDao;
	}

	public void setPartnerDao(IPartnerDao partnerDao) {
		this.partnerDao = partnerDao;
	}

	public void setReceivableDao(IReceivableDao receivableDao) {
		this.receivableDao = receivableDao;
	}

	public void setPayableDao(IPayableDao payableDao) {
		this.payableDao = payableDao;
	}

	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}

	public void setSaleOrderDao(ISaleOrderDao saleOrderDao) {
		this.saleOrderDao = saleOrderDao;
	}

	public void setSaleOrderDetailsDao(ISaleOrderDetailsDao saleOrderDetailsDao) {
		this.saleOrderDetailsDao = saleOrderDetailsDao;
	}

	public void setQuotationService(QuotationService quotationService) {
		this.quotationService = quotationService;
	}

}
